Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Assets] Implement pallet-assets-holder #4530

Open
wants to merge 95 commits into
base: master
Choose a base branch
from

Conversation

pandres95
Copy link
Contributor

@pandres95 pandres95 commented May 21, 2024

Closes #4315

@pandres95 pandres95 requested a review from a team as a code owner May 21, 2024 05:43
@pandres95 pandres95 marked this pull request as draft May 21, 2024 05:43
@pandres95 pandres95 force-pushed the pallet-assets-holder branch from c627c51 to 89ea43a Compare June 17, 2024 16:53
…th the tokens' _balance components_ model.

On the most recent documentation about tokens (both _fungible_ and _fungibles_ (sets)), the model for calculating the different balance components is explained. The prior implementation of `pallet-assets` featured a weird definition of how to handle them that was not in line with the expected (see <https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html#holds-and-freezes>) definition of tokens.

This commit changes this implementation for methods `reducible_balance` and `can_decrease` to introduce the calculation of `spendable` balance, and the consequences derived of decreasing a balance that may include both `frozen` and `held` balances.
@pandres95 pandres95 marked this pull request as ready for review July 11, 2024 09:45
@pandres95 pandres95 requested review from athei and a team as code owners July 11, 2024 09:45
@bkchr
Copy link
Member

bkchr commented Jul 24, 2024

@joepetrowski @muharem can you please take a look at this and if we need this?

Copy link
Contributor

@muharem muharem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pandres95 I do not really understand the plan. I see only first step in the issue. also are you sure we need this new trait? can we do the same with fungibles traits? I see that we have a similar FrozenBalance trait, but it probably was introduced before the fungibles was. can we bring the hold implementation with a single PR? it would make it more clear and we get it faster. this PR wont bring anything useful, only breaking changes.

@pandres95
Copy link
Contributor Author

pandres95 commented Jul 25, 2024

Sure! Can complete the second step in the same PR.

The reason behind this trait is that in some prior meeting Gav advised against exhaustively modifying some core pallets like pallet-assets and instead recommended extending them. That is, precisely the reasoning for having created pallet-assets-freezer.

@muharem
Copy link
Contributor

muharem commented Jul 25, 2024

@pandres95 yes, it should be done as an extension. there is also a died hook, the new trait make sense to me now.
so I would only advise to have a single PR, since HeldBalance along does not bring anything, and only breaking changes.
if introduced and merged separately, it is possible to get the HeldBalance and the holder pallet in different release versions. Two separate audits would be required. also I think we can review it better in a single PR.

@pandres95 pandres95 changed the title [Assets] Define HeldBalance [Assets] Implement pallet-assets-holder Jul 29, 2024
@paritytech-review-bot paritytech-review-bot bot requested a review from a team August 1, 2024 02:28
@pandres95
Copy link
Contributor Author

@muharem the pallet implementation is done and ready to review

@pandres95 pandres95 requested a review from muharem August 1, 2024 02:33
Copy link
Contributor Author

@pandres95 pandres95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this (thanks @ggwpez)

substrate/frame/assets-holder/src/lib.rs Outdated Show resolved Hide resolved
…rency::unreserve` that are followed by a potential failure of `dead_account`.

This would prevent cases where `refund` is called externally by another pallet, and not as a part of a direct extrinsic call within the pallet.
@pandres95 pandres95 requested a review from ggwpez November 6, 2024 16:31
@pandres95
Copy link
Contributor Author

pandres95 commented Nov 12, 2024

@gui1117 AFAIK, I've already addressed the changes you requested on your review. Let me know if there's something additional you need from my end. 😁

substrate/frame/assets/src/types.rs Outdated Show resolved Hide resolved
substrate/frame/assets/src/functions.rs Outdated Show resolved Hide resolved
@pandres95 pandres95 force-pushed the pallet-assets-holder branch from 7105fc3 to 4f50052 Compare November 27, 2024 14:24
@pandres95 pandres95 requested a review from muharem November 27, 2024 14:31
@pandres95 pandres95 force-pushed the pallet-assets-holder branch from 3d79a10 to 17e4b16 Compare November 27, 2024 15:46
@pandres95 pandres95 force-pushed the pallet-assets-holder branch from 48fe5d3 to 19e59ed Compare December 9, 2024 04:06
@pandres95 pandres95 force-pushed the pallet-assets-holder branch from 19e59ed to f2d33e0 Compare December 9, 2024 04:21
umbrella/Cargo.toml Outdated Show resolved Hide resolved
@@ -575,7 +607,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {

// Execute hook outside of `mutate`.
if let Some(Remove) = target_died {
T::Freezer::died(id, target);
T::Freezer::died(id.clone(), target);
T::Holder::died(id, target);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called from burn. I don't where it is check that the account is allowed to die. Are we ok that admin can kill the account even when there some on hold?

Copy link
Contributor Author

@pandres95 pandres95 Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really.

This is the exact reason why we had such a nightmare working on the ensures before an account could die. Because it's mandatory that an account doesn't have assets on hold before declaring it as dead.

This is a hook, not intended to burn up resources, but to make proper cleanup steps on external systems (if any needed) whenever an account is marked as dead (hence, informing the account already died).

That's also why its Freezer counterpart is also called that way.

Maybe I forgot to put an ensure here? Let me check. 👀

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be ensure no freezes and holds for decrease_balance as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done on a37b00b.

// Pre-check that an account can die if is below min balance
if source_account.balance < details.min_balance {
source_died =
Some(Self::dead_account(source, details, &source_account.reason, false));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does mutate the state, should be called ones

Copy link
Contributor Author

@pandres95 pandres95 Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this specific case, we're safe.

  1. Since the block for Asset::try_mutate hasn't finished yet, failing the ensure at this point would cause no mutations for details.
  2. Also, no dest account mutations happened here because we're doing this before the Account::try_mutate block.
  3. Finally, mutations for source_account only get saved at the end, much later than this step (see lines 728, 732).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn dead_account modifies the storage frame_system::Account and potentially anything.
Those are not reverted AFAICT

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me write a couple of additional tests to assert something, because from what I've seen in previous changes I've done in this sense is that if you run these ensures before knowing the account might die is that you get false positives (the call fails, but it was never dying).

@@ -575,7 +607,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {

// Execute hook outside of `mutate`.
if let Some(Remove) = target_died {
T::Freezer::died(id, target);
T::Freezer::died(id.clone(), target);
T::Holder::died(id, target);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be ensure no freezes and holds for decrease_balance as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Define and implement Hold for Assets
9 participants